package com.feeyo.monitor.rest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.feeyo.monitor.cache.CacheManager;
import com.feeyo.monitor.domain.*;
import com.feeyo.monitor.dto.UserDTO;
import com.feeyo.monitor.service.*;
import com.feeyo.monitor.utils.*;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.postgresql.util.PGobject;
import org.postgresql.util.PSQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.xml.transform.Result;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.*;

@RestController
//@RequestMapping(value="/user")
public class UserRestController {
	private static final Logger logger = LoggerFactory.getLogger(UserRestController.class);
	
	@Autowired
	UserService userService;
	@Autowired
    UserVehiclePermissionService userVehiclePermissionService;
    @Autowired
    CacheManager cacheManager;
    @Autowired
    DepartmentService departmentService;
    @Autowired
    AirportService airportService;
    @Autowired
    VehicleService vehicleService;

    @RequestMapping(value="/user/list", method=RequestMethod.GET)
    public ResultData<Object> userList(@RequestParam(value="userName",required=false) String userName,
                                       @RequestParam(value="userId",required=false) String userId,
                                        @RequestParam(value = "pageNumber",required=true) int pageNumber,
                                        @RequestParam(value = "pageSize",required=true) int pageSize) {

        logger.info("userNanme =>" + userName);

        ResultData<Object> rd = new ResultData<Object>();
        Map<String,Object> param = new HashMap<>();

        if (userName != null) {
            try {
                userName = URLDecoder.decode(userName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            param.put("userName", userName);
        }

        if (userId != null) {
            User users = userService.selectByPrimaryKey(userId);
            if(!users.getAdminis())
                param.put("airport", users.getAirport());
        }

        PageInfo result = null;
        result  =  userService.selectByPage(param,pageNumber,pageSize);

        List r = result.getList();
        for(Object item :r){
            HashMap hm  = (HashMap)item;
            PGobject obj = (PGobject)hm.get("permissions");
            JSONObject json = (JSONObject) JSON.parse(obj.toString());
            String dept = json.getString("department");
            if (dept.equals("*"))
                hm.put("deptname","*");
            else{
                JSONArray jsonArr = JSON.parseArray(json.getString("department"));
                if(jsonArr!=null && jsonArr.size()<2) {
                    jsonArr.forEach(t -> {
                        try {
                            if (!t.toString().equals("")) {
                                Department dt = departmentService.selectByPrimaryKey(t.toString());
                                String deptName = "";
                                deptName = dt.getName() + "-" + deptName;
                                while (dt.getParentid() != null) {
                                    dt = departmentService.selectByPrimaryKey(dt.getParentid().toString());
                                    deptName = dt.getName() + "-" + deptName;
                                }
                                deptName = deptName.substring(0, deptName.length() - 1);
                                hm.put("deptname", deptName);

                            }
                        } catch (PSQLException e) {
                            e.printStackTrace();
                        }
                    });
                }
            }
            //hm.put("airport",json.getString("airport"));

        }
        rd.setCode(GloabalConstant.SUCCESS);
        rd.setData(result);
        return rd;
    }

	@RequestMapping(value="/user/get/{userId}", method=RequestMethod.GET)
	public ResultData<UserDTO> getUser(@PathVariable String userId){
		ResultData<UserDTO> rd = new ResultData<UserDTO>();
		User user = null;
        UserDTO userDTO = new UserDTO();
		try{
		    user = userService.selectByPrimaryKey(userId);
            Map<Object,Object> permMap = userVehiclePermissionService.selectByUserId(userId);
            userDTO = new UserDTO();
            userDTO.setId(userId);
            userDTO.setAirport(user.getAirport());
            userDTO.setAdminis(user.getAdminis());
            userDTO.setAlarm((Boolean) permMap.get("alarm"));
            userDTO.setDeptManager((Boolean) permMap.get("deptManager"));
            userDTO.setDepts((String) permMap.get("department"));
            userDTO.setExpire(user.getExpire());
            userDTO.setLimitEdit((Boolean)permMap.get("limitEdit"));
            userDTO.setLimitVisit((Boolean)permMap.get("limitVisit"));
            userDTO.setMonitorVisit((Boolean)permMap.get("monitorVisit"));
            userDTO.setRunStat((Boolean)permMap.get("runStat"));
            userDTO.setUsername(user.getUsername());
            userDTO.setVehicleManager((Boolean)permMap.get("vehicleManager"));

            userDTO.setVehicleEdit((Boolean)permMap.get("vehicleEdit"));
            userDTO.setDeptEdit((Boolean)permMap.get("deptEdit"));
            userDTO.setUserManager((Boolean)permMap.get("userManager"));
            userDTO.setUserEdit((Boolean)permMap.get("userEdit"));
            userDTO.setAlarmDelete((Boolean)permMap.get("alarmDelete"));
		}catch(Exception e){
			logger.error("*****has error******");
			e.printStackTrace();
			rd.setCode(GloabalConstant.FAILED);
			rd.setMessage(e.getMessage());
			return rd;
		}
		rd.setData(userDTO);
		rd.setCode(0L);
		return rd;
	}

    @RequestMapping(value="/user/delete/{userId}", method=RequestMethod.GET)
    public ResultData<Object> deleteUser(@PathVariable String userId){
        ResultData<Object> rd = new ResultData<Object>();
        try{
            userService.updateDeleteStatus(userId);
            userVehiclePermissionService.updateDeleteStatus(userId);
        }catch(Exception e){
            logger.error("*****has error******");
            e.printStackTrace();
            rd.setCode(GloabalConstant.FAILED);
            rd.setMessage(e.getMessage());
            return rd;
        }
        return rd;
    }

    @RequestMapping(value="/user/save", method=RequestMethod.POST)
    public ResultData<Object> saveOrUpdate(@ModelAttribute UserDTO userDTO){
        ResultData<Object> rd = new ResultData<Object>();

        if (userDTO.getId() == null) {
            List users = userService.selectByUserName(userDTO.getUsername());
            if (users.size() > 0) {
                rd.setCode(GloabalConstant.FAILED);
                rd.setMessage("UserAlreadyExistException");
                return rd;
            }
        }
//        catch(UserAlreadyExistException e){
//            logger.error("*****user aleady exist******");
//            e.printStackTrace();
//            rd.setCode(GloabalConstant.FAILED);
//            rd.setMessage("UserAlreadyExistException");
//            return rd;
//        }
        if (userDTO.getId() == null){
            User user = new User();
            user.setUsername(userDTO.getUsername());
            user.setPassword(userDTO.getPassword());
            user.setExpire(userDTO.getExpire());
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            user.setToken(uuid);
            user.setAdminis(userDTO.getAdminis());
            user.setAirport(userDTO.getAirport());
            userService.insertSelective(user);

            Map<String,String> passParam = new HashMap();
            passParam.put("id",user.getId());
            passParam.put("password",userDTO.getPassword());
            userService.updatePassword(passParam);

            UserVehiclePermission userVehiclePermission = new UserVehiclePermission();
            userVehiclePermission.setUserid(user.getId());
            JSONObject perm = new JSONObject();
            perm.put("airport",userDTO.getAirport().split(","));
            perm.put("company","*");
            perm.put("department",userDTO.getDepts().split(","));
            perm.put("vehicletype","*");
            perm.put("monitorVisit",userDTO.getMonitorVisit());
            perm.put("limitVisit",userDTO.getLimitVisit());
            perm.put("limitEdit",userDTO.getLimitEdit());
            perm.put("runStat",userDTO.getRunStat());
            perm.put("alarm",userDTO.getAlarm());
            perm.put("vehicleManager",userDTO.getVehicleManager());
            perm.put("deptManager",userDTO.getDeptManager());

            perm.put("vehicleEdit",userDTO.getVehicleEdit());
            perm.put("deptEdit",userDTO.getDeptEdit());
            perm.put("userManager",userDTO.getUserManager());
            perm.put("userEdit",userDTO.getUserEdit());
            perm.put("alarmDelete",userDTO.getAlarmDelete());

            userVehiclePermission.setPermissions(perm.toJSONString());
            userVehiclePermissionService.insertSelective(userVehiclePermission);
        }else{
            User user = new User();
            user.setId(userDTO.getId());
            user.setUsername(userDTO.getUsername());
            //user.setPassword(userDTO.getPassword());
            user.setExpire(userDTO.getExpire());
            user.setAdminis(userDTO.getAdminis());
            user.setAirport(userDTO.getAirport());
            userService.updateByPrimaryKeySelective(user);

            Map<Object,Object> permMap = userVehiclePermissionService.selectByUserId(userDTO.getId());
            UserVehiclePermission userVehiclePermission = new UserVehiclePermission();
            userVehiclePermission.setId((Integer) permMap.get("id"));
            userVehiclePermission.setUserid(user.getId());
            JSONObject perm = new JSONObject();
            perm.put("airport",userDTO.getAirport().split(","));
            perm.put("company","*");
            perm.put("department",userDTO.getDepts().split(","));
            perm.put("vehicletype","*");
            perm.put("monitorVisit",userDTO.getMonitorVisit());
            perm.put("limitVisit",userDTO.getLimitVisit());
            perm.put("limitEdit",userDTO.getLimitEdit());
            perm.put("runStat",userDTO.getRunStat());
            perm.put("alarm",userDTO.getAlarm());
            perm.put("vehicleManager",userDTO.getVehicleManager());
            perm.put("deptManager",userDTO.getDeptManager());

            perm.put("vehicleEdit",userDTO.getVehicleEdit());
            perm.put("deptEdit",userDTO.getDeptEdit());
            perm.put("userManager",userDTO.getUserManager());
            perm.put("userEdit",userDTO.getUserEdit());
            perm.put("alarmDelete",userDTO.getAlarmDelete());

            userVehiclePermission.setPermissions(perm.toJSONString());
            userVehiclePermissionService.updateByPrimaryKeySelective(userVehiclePermission);
        }
        return rd;
    }

    @RequestMapping(value="/user/password", method=RequestMethod.POST)
    public ResultData<Object> updatePassword(@ModelAttribute UserDTO userDTO){
        ResultData<Object> rd = new ResultData<Object>();
        try{
            Map<String,String> passParam = new HashMap();
            passParam.put("id",userDTO.getId());
            passParam.put("password",userDTO.getPassword());
            userService.updatePassword(passParam);
        }catch (Exception e){
            e.printStackTrace();
            rd.setCode(GloabalConstant.FAILED);
            rd.setMessage(e.getMessage());
        }
        return rd;
    }

	@RequestMapping(value="/monitor/login", method=RequestMethod.POST)
	public ResultData<Object> monitorlogin(@RequestParam(value="userName",required=true) String userName,
									 @RequestParam(value="password",required=true) String password){
        ResultData<Object> rd = new ResultData<Object>();
        Map<String,String> param = new HashMap<String,String>();
        param.put("userName",userName);
        param.put("password", password);
        List<Map> result=null;
        try{
            result = userService.login(param);
        }catch(Exception e){
            logger.error("*****has error******");
            e.printStackTrace();
            rd.setCode(GloabalConstant.FAILED);
            rd.setMessage(e.getMessage());
            return rd;
        }
        if ((result != null) && (result.size() > 0)) {
            Map resultMap = result.get(0);
            String userId = resultMap.get("userid").toString();
            Map<Object, Object> perm = userVehiclePermissionService.selectByUserId(userId);


            resultMap.putAll(perm);
            rd.setCode(GloabalConstant.SUCCESS);
            rd.setData(resultMap);
        }
        else {
            rd.setCode(GloabalConstant.LOGIN_FAILED);
            rd.setMessage("login failed");
        }
        return  rd;
	}

    @RequestMapping(value="/token/login", method=RequestMethod.POST)
    public ResultData<Object> tokenlogin(@RequestParam(value="token",required=true) String token){
        ResultData<Object> rd = new ResultData<Object>();

        List<Map> result=null;
        try{
            result = userService.tokenLogin(token);
        }catch(Exception e){
            logger.error("*****has error******");
            e.printStackTrace();
            rd.setCode(GloabalConstant.FAILED);
            rd.setMessage(e.getMessage());
            return rd;
        }
        if ((result != null) && (result.size() > 0)) {
            Map resultMap = result.get(0);
            String userId = resultMap.get("userid").toString();
            Map<Object, Object> perm = userVehiclePermissionService.selectByUserId(userId);
            resultMap.putAll(perm);
            rd.setCode(GloabalConstant.SUCCESS);
            rd.setData(resultMap);
        }
        else {
            rd.setCode(GloabalConstant.LOGIN_FAILED);
            rd.setMessage("login failed");
        }
        return  rd;
    }

	@RequestMapping(value="/manager/login", method=RequestMethod.POST)
	public ResultData<Object> managerlogin(@RequestParam(value="userName",required=true) String userName,
									 @RequestParam(value="password",required=true) String password){
        ResultData<Object> rd = new ResultData<Object>();
        Map<String,String> param = new HashMap<String,String>();
        param.put("userName",userName);
        param.put("password", password);
        List<Map> result=null;
        try{
            result = userService.login(param);
        }catch(Exception e){
            logger.error("*****has error******");
            e.printStackTrace();
            rd.setCode(GloabalConstant.FAILED);
            rd.setMessage(e.getMessage());
            return rd;
        }
        if ((result != null) && (result.size() > 0)) {
            Map resultMap = result.get(0);
            String userId = resultMap.get("userid").toString();
            Map<Object, Object> perm = userVehiclePermissionService.selectByUserId(userId);
            resultMap.putAll(perm);
            rd.setCode(GloabalConstant.SUCCESS);
            rd.setData(resultMap);
        }
        else
            rd.setCode(GloabalConstant.LOGIN_FAILED);
        return  rd;
	}

    @RequestMapping(value="/manager/pastvehicle/{period}", method=RequestMethod.GET)
    public ResultData<String> pastVehicle(@PathVariable String period){
        ResultData<String> rd = new ResultData<>();
        Set result = (Set) cacheManager.keys("*");
        long now = new Date().getTime()/1000;
        long interval = 0;
        if (period.toLowerCase().equals("week"))
            interval = 60 * 60 * 24 * 7;
        else if (period.toLowerCase().equals("month"))
            interval = 60 * 60 * 24 * 30;
        else
            return null;

        StringBuffer sbPast = new StringBuffer();
        StringBuffer sbNotPast = new StringBuffer();

        int countPast = 0;
        int countNotPast = 0;


        for(Object item :result) {
            String key = (String) item;
            if (key.startsWith("loginCacheNFC"))
                continue;
            if (key.startsWith("sess"))
                continue;
            if (key.startsWith("loginCacheVehicle"))
                continue;
            if (key.startsWith("lock"))
                continue;
            if(key.equals("a"))
                continue;
            if(key.equals("writeToRiakTSCounter"))
                continue;

            String stime = (String) cacheManager.hashGet(key, "time");
            long time = -1;
            logger.info("key:"+key);
            if(stime.contains("E9")) {
                double e9 = Double.parseDouble(stime);
                BigDecimal bd=new BigDecimal(e9);
                time = bd.longValue();
            }else
                time = Long.parseLong(stime);

            if ((now - time) > interval){
                //Vehicle v = vehicleService.selectByPrimaryKey(key);
                countPast ++;
                sbPast.append("'"+key+"',");
            }else {
                countNotPast++;
                sbNotPast.append("'" + key + "',");
            }
        }

        //rd.setData(sbPast.toString() + "||" + sbNotPast.toString());
        rd.setData("未上线:"+countPast + ";上线:"+countNotPast +"||未上线:"+ sbPast.toString() + "||上线:" + sbNotPast.toString());
        rd.setCode(0L);
        return rd;
    }

    @RequestMapping(value="/airport/list", method=RequestMethod.GET)
    public ResultData<Object> airport(){
        ResultData<Object> rd = new ResultData<Object>();
        List<Airport> result = null;
        try{
            result = airportService.selectList();
        }catch(Exception e){
            logger.error("*****has error******");
            e.printStackTrace();
            rd.setCode(GloabalConstant.FAILED);
            rd.setMessage(e.getMessage());
            return rd;
        }
        rd.setCode(GloabalConstant.SUCCESS);
        rd.setData(result);
        return rd;
    }

}
